package pl.edu.agh.neuraleconomy.core.experiment;

import java.io.File;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;

import pl.edu.agh.neuraleconomy.common.utils.DateUtils;
import pl.edu.agh.neuraleconomy.core.decision.IDecisionMaker;
import pl.edu.agh.neuraleconomy.core.decision.SimpleDecisionMaker;
import pl.edu.agh.neuraleconomy.core.experiment.filter.MaxAmountCompanyFilter;
import pl.edu.agh.neuraleconomy.core.experiment.filter.StandardDeviationFilter;
import pl.edu.agh.neuraleconomy.core.experiment.statistics.AbstractStatictic;
import pl.edu.agh.neuraleconomy.core.experiment.statistics.ChartStatistic;
import pl.edu.agh.neuraleconomy.core.experiment.statistics.TransactionStatistic;
import pl.edu.agh.neuraleconomy.core.experiment.statistics.WealthValueStatistic;
import pl.edu.agh.neuraleconomy.core.simulation.SimulationEngine;
import pl.edu.agh.neuraleconomy.core.simulation.Transaction;
import pl.edu.agh.neuraleconomy.core.ta.advice.Advice;
import pl.edu.agh.neuraleconomy.core.ta.advice.AdvisorComposite;
import pl.edu.agh.neuraleconomy.core.ta.advice.IAdvisor;
import pl.edu.agh.neuraleconomy.core.ta.advice.PredictionAdvisor;
import pl.edu.agh.neuraleconomy.core.ta.advice.ROCAdvisor;
import pl.edu.agh.neuraleconomy.model.exchange.Company;

public class ExperimentRunner {
	private static List<Company> companies = null;

	public static void main(String[] args) {
		List<ExperimentSet> sets = new LinkedList<ExperimentSet>();

		sets.add(new ExperimentSet("Prediction_04_00_s_long", prepareSimulation(), new SimpleDecisionMaker(0.4, 0.0),
				new AdvisorComposite(new AdvisorComposite.WeightedAdvisor(new PredictionAdvisor(), 1.0))));
		//
		// sets.add(new ExperimentSet("1Prediction_05ROC5_04_02_s",
		// prepareSimulation(), new SimpleDecisionMaker(0.4, 0.2), new
		// AdvisorComposite(
		// new AdvisorComposite.WeightedAdvisor(new ROCAdvisor(5), 0.5), new
		// AdvisorComposite.WeightedAdvisor(new PredictionAdvisor(),
		// 1.0))));
		//
		// RSI
		// sets.add(new ExperimentSet("ROC5_RSI5_04_00_s", prepareSimulation(),
		// new SimpleDecisionMaker(0.4, 0.0), new AdvisorComposite(
		// new AdvisorComposite.WeightedAdvisor(new RSIAdvisor(5), 1.0), new
		// AdvisorComposite.WeightedAdvisor(new ROCAdvisor(5), 1.0))));
		//
		// sets.add(new ExperimentSet("ROC5_RSI5_04_02_s", prepareSimulation(),
		// new SimpleDecisionMaker(0.4, 0.2), new AdvisorComposite(
		// new AdvisorComposite.WeightedAdvisor(new RSIAdvisor(5), 1.0), new
		// AdvisorComposite.WeightedAdvisor(new ROCAdvisor(5), 1.0))));
		//
		// sets.add(new ExperimentSet("ROC5_Prediction_RSI5_04_02_s",
		// prepareSimulation(), new SimpleDecisionMaker(0.4, 0.2),
		// new AdvisorComposite(new AdvisorComposite.WeightedAdvisor(new
		// RSIAdvisor(5), 1.0), new AdvisorComposite.WeightedAdvisor(
		// new PredictionAdvisor(), 1.0), new
		// AdvisorComposite.WeightedAdvisor(new ROCAdvisor(5), 1.0))));

		// sets.add(new ExperimentSet("5_05Prediction_1RSI5_04_02_s",
		// prepareSimulation(), new SimpleDecisionMaker(0.4, 0.2), new
		// AdvisorComposite(
		// new AdvisorComposite.WeightedAdvisor(new RSIAdvisor(5), 1.0), new
		// AdvisorComposite.WeightedAdvisor(new PredictionAdvisor(),
		// 0.5))));
		//
		// sets.add(new ExperimentSet("1Prediction_05RSI5_04_02_s",
		// prepareSimulation(), new SimpleDecisionMaker(0.4, 0.2), new
		// AdvisorComposite(
		// new AdvisorComposite.WeightedAdvisor(new RSIAdvisor(5), 0.5), new
		// AdvisorComposite.WeightedAdvisor(new PredictionAdvisor(),
		// 1.0))));
		//
		// // EMA
		// sets.add(new ExperimentSet("EMA13_04_00_s", prepareSimulation(), new
		// SimpleDecisionMaker(0.4, 0.0), new AdvisorComposite(
		// new AdvisorComposite.WeightedAdvisor(new EMAAdvisor(13), 1.0))));
		//
		// sets.add(new ExperimentSet("EMA13_04_02_s", prepareSimulation(), new
		// SimpleDecisionMaker(0.4, 0.2), new AdvisorComposite(
		// new AdvisorComposite.WeightedAdvisor(new EMAAdvisor(13), 1.0))));

		// sets.add(new ExperimentSet("Prediction_EMA13_04_00_s",
		// prepareSimulation(), new SimpleDecisionMaker(0.4, 0.0),
		// new AdvisorComposite(new AdvisorComposite.WeightedAdvisor(new
		// EMAAdvisor(13), 1.0), new AdvisorComposite.WeightedAdvisor(
		// new PredictionAdvisor(), 1.0))));
		//
		// sets.add(new ExperimentSet("05Prediction_1EMA13_04_00_s",
		// prepareSimulation(), new SimpleDecisionMaker(0.4, 0.0),
		// new AdvisorComposite(new AdvisorComposite.WeightedAdvisor(new
		// EMAAdvisor(13), 1.0), new AdvisorComposite.WeightedAdvisor(
		// new PredictionAdvisor(), 0.5))));
		//
		// sets.add(new ExperimentSet("1Prediction_0.5EMA13_04_00_s",
		// prepareSimulation(), new SimpleDecisionMaker(0.4, 0.0),
		// new AdvisorComposite(new AdvisorComposite.WeightedAdvisor(new
		// EMAAdvisor(13), 0.5), new AdvisorComposite.WeightedAdvisor(
		// new PredictionAdvisor(), 1.0))));

//		sets.add(new ExperimentSet("Prediction_04_02_s", prepareSimulation(), new SimpleDecisionMaker(0.4, 0.2), new AdvisorComposite(
//				new AdvisorComposite.WeightedAdvisor(new PredictionAdvisor(), 1.0))));
//		
//		sets.add(new ExperimentSet("Prediction_04_00_s", prepareSimulation(), new SimpleDecisionMaker(0.4, 0.0), new AdvisorComposite(
//				new AdvisorComposite.WeightedAdvisor(new PredictionAdvisor(), 1.0))));
//		
//		sets.add(new ExperimentSet("Prediction_00_02_s", prepareSimulation(), new SimpleDecisionMaker(0.0, 0.2), new AdvisorComposite(
//				new AdvisorComposite.WeightedAdvisor(new PredictionAdvisor(), 1.0))));

		for (ExperimentSet set : sets) {
			runExperiment(set);
		}
	}

	private static void runExperiment(ExperimentSet set) {
		final String sufix = set.getDescription();// "Prediction_ROC5_04_02_s";

		Experiment experiment = new Experiment();
		experiment.setCompanies(companies);
		experiment.setSimulation(set.getSimulation());// prepareSimulation());
		experiment.setAdvisor(set.getAdvisor());// prepareAdvisor());
		experiment.setDecisionMaker(set.getDecisionMaker());// prepareDecisionMaker());
		experiment.addCompanyFilter(new MaxAmountCompanyFilter(100));
		experiment.addCompanyFilter(new StandardDeviationFilter(0.2, 0.3));
		experiment.addCompanyFilter(new MaxAmountCompanyFilter(60));
		experiment.setEndDate(DateUtils.getByString("2013-07-01"));
		experiment.getStatistics().add(new WealthValueStatistic(new File("D:\\bagno\\wealth\\"), "wealth".concat(sufix)));
		experiment.getStatistics().add(new TransactionStatistic(new File("D:\\bagno\\transactions\\"), "transaction".concat(sufix)));
		experiment.getStatistics().add(new AbstractStatictic() {

			@Override
			public void iteration(Date date, SimulationEngine simulation, List<Advice> advices, List<Transaction> transactionsMade) {
				Logger.getLogger(getClass()).info(sufix.concat(" " + DateUtils.formatDate(date)));
			}
		});
		experiment.getStatistics().add(new ChartStatistic(sufix, "Wealth", "PLN", new File("D:\\bagno\\chart\\"), "chart".concat(sufix)));

		experiment.start();

		companies = experiment.getCompanies();
	}

	private static SimulationEngine prepareSimulation() {
		return new SimulationEngine(DateUtils.getByString("2012-09-01"), 10000.0, "experiment");
	}

	private static IAdvisor prepareAdvisor() {
		AdvisorComposite composite = new AdvisorComposite();
		composite.addAdvisor(new ROCAdvisor(5), 1.0);
		composite.addAdvisor(new PredictionAdvisor(), 1.0);
		return composite;
		// return new ROCAdvisor(5);

	}

	private static IDecisionMaker prepareDecisionMaker() {
		SimpleDecisionMaker dm = new SimpleDecisionMaker();

		dm.setMoneyPart(0.4);
		dm.setShortSellMoneyPart(0.2);

		return dm;
	}
}
